package com.example.mydemo.config;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import jakarta.annotation.PostConstruct;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Slf4j
@Data
@Configuration
@ConfigurationProperties(prefix = "spring.elasticsearch") // 修改前缀
public class ElasticSearchConfig {
    private Boolean open = true;
    private String hosts = "localhost:9200"; // 添加默认值
    private String userName = "";
    private String password = "";
    private String scheme = "http";
    private String clusterName = "elasticsearch";
    private int connectTimeOut = 5000;
    private int socketTimeOut = 30000;
    private int connectionRequestTimeOut = 5000;
    private int maxConnectNum = 100;
    private int maxConnectNumPerRoute = 100;
    private String apiKey = "";
//@Slf4j
//@Data
//@Configuration
//@ConfigurationProperties(prefix = "spring.elasticsearch")
//public class ElasticSearchConfig {
//
//    // 是否开启ES
//    private Boolean open;
//
//    // es 集群host ip 地址
//    private String hosts;
//
//    // es用户名
//    private String userName;
//
//    // es密码
//    private String password;
//
//    // es 请求方式
//    private String scheme;
//
//    // es集群名称
//    private String clusterName;
//
//    // es 连接超时时间
//    private int connectTimeOut;
//
//    // es socket 连接超时时间
//    private int socketTimeOut;
//
//    // es 请求超时时间
//    private int connectionRequestTimeOut;
//
//    // es 最大连接数
//    private int maxConnectNum;
//
//    // es 每个路由的最大连接数
//    private int maxConnectNumPerRoute;
//
//    // es api key
//    private String apiKey;


    public RestClientBuilder creatBaseConfBuilder(String scheme){


        // 1. 单节点ES Host获取
        String host = hosts.split(":")[0];
        String port = hosts.split(":")[1];
        // The value of the schemes attribute used by noSafeRestClient() is http
        // but The value of the schemes attribute used by safeRestClient() is https
        HttpHost httpHost = new HttpHost(host, Integer.parseInt(port),scheme);

        // 2. 创建构建器对象
        //RestClientBuilder: ES客户端库的构建器接口,用于构建RestClient实例;允许你配置与Elasticsearch集群的连接,设置请求超时,设置身份验证,配置代理等
        RestClientBuilder builder = RestClient.builder(httpHost);

        // 连接延时配置
        builder.setRequestConfigCallback(requestConfigBuilder -> {
            requestConfigBuilder.setConnectTimeout(connectTimeOut);
            requestConfigBuilder.setSocketTimeout(socketTimeOut);
            requestConfigBuilder.setConnectionRequestTimeout(connectionRequestTimeOut);
            return requestConfigBuilder;
        });

        // 3. HttpClient 连接数配置
        builder.setHttpClientConfigCallback(httpClientBuilder -> {
            httpClientBuilder.setMaxConnTotal(maxConnectNum);
            httpClientBuilder.setMaxConnPerRoute(maxConnectNumPerRoute);
            return httpClientBuilder;
        });

        return builder;
    }
    @PostConstruct
    public void init() {
        log.info("Elasticsearch configuration loaded: hosts={}, scheme={}", hosts, scheme);
    }
    /**
     * @function: 创建使用http连接来直接连接ES服务器的客户端
     * 如果@Bean没有指定bean的名称,那么这个bean的名称就是方法名
     */
    @Bean(name = "directConnectionESClient")
    public ElasticsearchClient directConnectionESClient() {
        // 检查 hosts 是否为空
        if (hosts == null || hosts.isEmpty()) {
            log.error("Elasticsearch hosts configuration is missing or empty");
            throw new IllegalArgumentException("Elasticsearch hosts configuration is required");
        }

        RestClientBuilder builder = creatBaseConfBuilder((scheme != null && scheme.equalsIgnoreCase("https")) ? "https" : "http");

        // 添加身份验证配置
        if (userName != null && !userName.isEmpty() && password != null && !password.isEmpty()) {
            CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
            credentialsProvider.setCredentials(AuthScope.ANY,
                    new UsernamePasswordCredentials(userName, password));

            builder.setHttpClientConfigCallback(httpClientBuilder -> {
                httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
                return httpClientBuilder;
            });
        }
//        else if (apiKey != null && !apiKey.isEmpty()) {
//            // 如果提供了 API Key，则使用 API Key 认证
//            builder.setHttpClientConfigCallback(httpClientBuilder -> {
//                httpClientBuilder.addInterceptorLast((HttpRequest request, HttpContext context) -> {
//                    request.addHeader("Authorization", "ApiKey " + apiKey);
//                });
//                return httpClientBuilder;
//            });
//        }
        else {
            log.warn("Elasticsearch authentication credentials are missing. Proceeding without authentication.");
        }

        // Create the transport with a Jackson mapper
        ElasticsearchTransport transport = new RestClientTransport(builder.build(), new JacksonJsonpMapper());

        // And create the API client
        ElasticsearchClient esClient = new ElasticsearchClient(transport);

        return esClient;
    }

}

